package rs.udd.service.document.indexer.handler;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.util.PDFTextStripper;

import rs.udd.exceptions.IncompleteIndexDocumentException;
import rs.udd.model.Advertiser;
import rs.udd.service.document.analyzer.filter.CyrillicLatinConverter;
import rs.udd.service.dto.advert.AdvertDto;
import rs.udd.service.util.FileUtil.FileTypes;
import rs.udd.service.util.SecurityUtil;

public class PDFHandler extends DocumentHandler {

//	private static final Logger LOGGER = LogManager.getLogger(PDFHandler.class);
	
	// default meta data
	public static final String ID = "Id";
	public static final String TYPE = "Type";
	public static final String TITLE = "Title";
	public static final String FILE_NAME = "FileName";
	public static final String LOCATION = "Location";
	public static final String TEXT = "Text";
	public static final String AUTHOR = "Author";
	public static final String KEY_WORD = "Keywords";
	public static final String ABSTRACT_TEXT = "AbstractText";
	public static final String CATEGORIES = "Categories";
	
	public static final String META_DATA_SEPARATOR = ",";
	
	private String id;
	
	public PDFHandler(String id) {
		this.id = id;
	}
	
	@Override
	public Document getDocument(File file) throws IncompleteIndexDocumentException {
		Document doc = new Document();

		String error = "";
		try {
			StringField fieldId = new StringField(PDFHandler.ID, id, Store.YES);
			doc.add(fieldId);
			
			StringField fieldType = new StringField(PDFHandler.TYPE, FileTypes.CV.name(), Store.YES);
			doc.add(fieldType);
			
			TextField fileNameField = new TextField(PDFHandler.FILE_NAME, file.getName(), Store.YES);
			doc.add(fileNameField);
			
			StringField locationField = new StringField(PDFHandler.LOCATION, file.getCanonicalPath(), Store.YES);
			doc.add(locationField);
			
			// napraviti pdf parser
			PDFParser parser = new PDFParser(new FileInputStream(file));
			// izvrsiti parsiranje
			parser.parse();
			// od parsera preuzeti parsirani pdf dokument (PDDocument)
			PDDocument pdf = parser.getPDDocument();
	
			// Upotrebiti text stripper klasu za ekstrahovanje teksta sa utf-8 kodnom stranom (PDFTextStripper)
			PDFTextStripper stripper = new PDFTextStripper("utf-8");
			String text = stripper.getText(pdf);
			if (StringUtils.isNotEmpty(text)) {
				doc.add(new TextField(PDFHandler.TEXT, CyrillicLatinConverter.cir2lat(text.trim()), Store.NO));
			} else {
				error += "Document without text\n";
			}
			
			// zatvoriti pdf dokument
			pdf.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e.getMessage());
			error = "Document is incomplete. An exception occured";
		}
		
		if (StringUtils.isNotEmpty(error)) {
			throw new IncompleteIndexDocumentException(error.trim());
		}
		
		return doc;
	}
	
	@Override
	public Document getDocument(File file, AdvertDto advertDto) throws IncompleteIndexDocumentException {
		Document doc = new Document();
		
		String error = "";
		try {
			doc = getDocument(file);	// index common attributes for CV and advert
			
			// napraviti pdf parser
			PDFParser parser = new PDFParser(new FileInputStream(file));
			// izvrsiti parsiranje
			parser.parse();
			// od parsera preuzeti parsirani pdf dokument (PDDocument)
			PDDocument pdf = parser.getPDDocument();
			
			// iz dokumenta izvuci objekat u kojem su svi metapodaci (PDDocumentInformation)
			PDDocumentInformation info = pdf.getDocumentInformation();

			StringField fieldId = new StringField(PDFHandler.ID, id, Store.YES);
			doc.add(fieldId);

			StringField fieldType = new StringField(PDFHandler.TYPE, FileTypes.ADVERT.name(), Store.YES);
			doc.add(fieldType);
			
			String author = info.getAuthor();
			if (StringUtils.isNotEmpty(author)) {
				doc.add(new TextField(PDFHandler.AUTHOR, author.trim(), Store.YES));
			} else if (advertDto != null){
				doc.add(new TextField(PDFHandler.TITLE, advertDto.getMetaAuthor(), Store.YES));
			}
				
			String title = info.getTitle();
			if (StringUtils.isNotEmpty(title)) { 
				doc.add(new TextField(PDFHandler.TITLE, title.trim(), Store.YES));
			} else if (advertDto != null){
				doc.add(new TextField(PDFHandler.TITLE, advertDto.getMetaTitle(), Store.YES));
			}
			
			String metaKeyWords = info.getKeywords();
			if (StringUtils.isNotEmpty(metaKeyWords)) {
				Set<String> keywords = handleCommaSeparatedValues(metaKeyWords);
				keywords.addAll(handleSpaceSeparatedValues(metaKeyWords));
				for (String kw : keywords) {
					doc.add(new TextField(PDFHandler.KEY_WORD, kw, Store.YES));
				}
			}
			
			if (advertDto != null) {
				doc.add(new TextField(PDFHandler.TITLE, advertDto.getTitle(), Store.YES));
				doc.add(new TextField(PDFHandler.ABSTRACT_TEXT, advertDto.getAbstractText(), Store.YES));
				
				Advertiser uploader = SecurityUtil.getLoggedUser(Advertiser.class); 
				doc.add(new TextField(PDFHandler.AUTHOR, uploader.getUsername(), Store.YES));
				
				String categoryNamesCommaSeparated = advertDto.getCategoryNames();
				Set<String> categoryNames = handleCommaSeparatedValues(categoryNamesCommaSeparated);
				for (String categoryName : categoryNames) {
					doc.add(new TextField(PDFHandler.CATEGORIES, categoryName, Store.YES));
				}
				
				String userKeywordsCommaSeparated = advertDto.getMetaKeywords();
				Set<String> keywords = handleCommaSeparatedValues(userKeywordsCommaSeparated);
				for (String kw : keywords) {
					doc.add(new TextField(PDFHandler.KEY_WORD, kw, Store.YES));
				}
			}

			// zatvoriti pdf dokument
			pdf.close();
		} catch (Exception e) {
			System.out.println("Greska pri konvertovanju pdf dokumenta");
			error = "Document is incomplete. An exception occured";
		}

		if (StringUtils.isNotEmpty(error)) {
			throw new IncompleteIndexDocumentException(error.trim());
		}

		return doc;
	}
	
	private Set<String> handleCommaSeparatedValues(String csv) {
		Set<String> retVal = new HashSet<String>();

		String[] array = csv.trim().split(PDFHandler.META_DATA_SEPARATOR);
		for (String value : array) {
			value = value.trim();
			retVal.add(value);
		}
		
		return retVal;
	}
	
	private Set<String> handleSpaceSeparatedValues(String ssv) {
		Set<String> retVal = new HashSet<String>();

		String[] array = ssv.trim().split(" ");
		for (String value : array) {
			value = value.trim();
			retVal.add(value);
		}
		
		return retVal;
	}
	

	public static boolean checkType(String[] typesToCheck, FileTypes desiredType) {
		boolean isDesiredType = false;
		for (String typeToCheck : typesToCheck) {
			FileTypes type = FileTypes.valueOf(typeToCheck);
			if (type == desiredType) {
				isDesiredType = true;
				break;
			}
		}
		
		return isDesiredType;
	}
	
}
